package pers.qianyu.diytomcat.util;

import cn.hutool.core.map.*;
import cn.hutool.core.util.*;

import java.io.*;
import java.net.*;
import java.nio.charset.*;
import java.util.*;

/**
 * @author mizzle rain
 * @date 2021-01-06 17:33
 */
public class MiniBrowser {
    public static byte[] getHttpBytes(String url, boolean gzip) {
        return getHttpBytes(url, gzip, null, true);
    }

    public static byte[] getHttpBytes(String url, boolean gzip, Map<String, String> params, boolean isGet) {
        byte[] result = null;
        try {
            URL u = new URL(url);
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(u.getHost(), u.getPort()), 1000);

            //<editor-fold desc="构造请求参数字符串">
            StringBuffer paramsStringBuffer = new StringBuffer();
            if (Objects.nonNull(params) && !params.isEmpty()) {
                for (String key : params.keySet()) {
                    String value = params.get(key);
                    paramsStringBuffer.append(key).append("=").append(value).append("&");
                }
                int length = paramsStringBuffer.length();
                paramsStringBuffer.delete(length - 1, length);
            }
            String paramsString = URLUtil.encode(paramsStringBuffer.toString(), "utf-8");
            //</editor-fold>

            //<editor-fold desc="构造请求头 + 请求体字符串">
            HashMap<Object, Object> headers = MapUtil.of(new String[][]{
                    {"Host", u.getHost() + ":" + u.getPort()},
                    {"Accept", "text/html"},
                    {"Connection", "close"},
                    {"User-Agent", "mini browser/java 1.8"},
            });
            if (gzip) {
                headers.put("Accept-Encoding", "gzip");
            }
            String path = u.getPath();
            if (StrUtil.isBlank(path)) {
                path = "/";
            }
            String firstLine = isGet ? String.format("GET %s HTTP/1.1\r\n",
                    path + (StrUtil.isEmpty(paramsString) ? "" : "?" + paramsString)) :
                    String.format("POST %s HTTP/1.1\r\n", path);
            StringBuffer sb = new StringBuffer();
            sb.append(firstLine);
            headers.forEach((k, v) -> sb.append(String.format("%s: %s\r\n", k, v)));
            sb.append("\r\n");
            if (!StrUtil.isEmpty(paramsString) && !isGet) {
                sb.append(paramsString);
            }
            //</editor-fold>

            //<editor-fold desc="发送请求">
            OutputStream out = socket.getOutputStream();
            out.write(sb.toString().getBytes(StandardCharsets.UTF_8));
            out.flush();
            //</editor-fold>

            //<editor-fold desc="读取响应">
            InputStream in = socket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) > 0) {
                baos.write(buffer, 0, len);
            }
            result = baos.toByteArray();
            //</editor-fold>
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getHttpString(String url, boolean gzip) {
        byte[] bytes = getHttpBytes(url, gzip);
        return new String(bytes, StandardCharsets.UTF_8);
    }

    public static String getHttpString(String url, boolean gzip, Map<String, String> params, boolean isGet) {
        byte[] bytes = getHttpBytes(url, gzip, params, isGet);
        return new String(bytes, StandardCharsets.UTF_8);
    }

    public static String getContentString(String url) {
        String httpString = getHttpString(url, false);
        return StrUtil.subAfter(httpString, "\r\n\r\n", false);
    }

    public static String getContentString(String url, Map<String, String> params, boolean isGet) {
        String httpString = getHttpString(url, false, params, isGet);
        return StrUtil.subAfter(httpString, "\r\n\r\n", false);
    }

    public static byte[] getContentBytes(String url) {
        return getContentBytes(url, false);
    }

    public static byte[] getContentBytes(String url, boolean gzip) {
        byte[] httpBytes = getHttpBytes(url, gzip);
        int i = 0;
        for (; i < httpBytes.length; i++) {
            if (httpBytes[i] == '\r' && httpBytes[i + 1] == '\n'
                    && httpBytes[i + 2] == '\r' && httpBytes[i + 3] == '\n') {
                break;
            }
        }
        i += 4;
        byte[] result = new byte[httpBytes.length - i];
        System.arraycopy(httpBytes, i, result, 0, result.length);
        return result;
    }

    public static void main(String[] args) {
        String url = "http://127.0.0.1:8081";
        String httpString = getHttpString(url, false);
        System.out.println(httpString);
    }
}
